#include "StdAfx.h"
#include "DWorld.h"
#include "../Engine/DResourceManagerSFML.h"
#include "DLayer.h"
#include "../Actors/DActorFactory.h"
#include "../Actors/DBackground.h"

DWorld::DWorld(boost::shared_ptr<DGame> game)
: m_game(game)
{
	m_resourceManager.reset(new DResourceManagerSFML);
}

DWorld::~DWorld(void)
{
}

void DWorld::update(float dt)
{
    foreach(boost::shared_ptr<DLayer> layer, m_layers)
    {
        layer->update(dt);
    }
}

void DWorld::render(boost::shared_ptr<DIRenderer> renderer)
{
    foreach(boost::shared_ptr<DLayer> layer, m_layers)
    {
        layer->render(renderer);
    }
}

bool DWorld::load(const std::string& strPath)
{
    // LOAD WORLD RESOURCES
    std::string resPath = strPath + "Resources.wld";
	std::ifstream inRes(resPath.c_str(), std::ifstream::in);

	char data[255];
	while(!inRes.eof())
	{
		bool bBackground = false;
		inRes.getline(data, 255);
		std::string strData(data);

        if(strData != "")
        {
		    if(boost::istarts_with(strData, "Backgrounds"))
		    {
			    bBackground = true;
		    }

		    if(!m_resourceManager->loadAnimation(strData, bBackground))
		    {
			    assert(false);
		    }
        }
	}

    inRes.close();

    std::string mapPath = strPath + "Map.wld";
    return loadMap(mapPath);
}

bool DWorld::loadMap(const std::string& strPath)
{
	// first layer is always main layer
	static bool bMainLayer = true;
    std::ifstream inMap(strPath.c_str(), std::ifstream::in);

    // put layers it in reverse order
    char data[255];
	while(!inMap.eof())
    {
        inMap.getline(data, 255);
        std::string strData(data);

        if(strData == "LAYER")
        {
            boost::shared_ptr<DLayer> layer;
            layer.reset(new DLayer(m_game.lock(), bMainLayer));
			bMainLayer = false;

            loadLayer(layer, inMap);
            m_layers.insert(m_layers.begin(), layer);
        }
    }

    return true;
}

bool DWorld::loadLayer(boost::shared_ptr<DLayer> layer, std::ifstream& in)
{
    char data[255];
    while(!in.eof())
    {
        // read file until we rich END_LAYER
        // check which type to make and then use DActorFactory to create objects
        // ENEMY
        // OBSTACLE
        // BACKGROUND
        // BOSS
        // ...
        in.getline(data, 255);
        std::string strLine(data);

        if(strLine == "END_LAYER")
        {
            return true;
        }
        else if(boost::istarts_with(strLine, "ENEMY"))
        {
            // extract data from string
            std::vector<std::string> result;
            boost::split(result, strLine, boost::is_any_of(" "));
            std::string strEnemyType = result[1];
            float startX = boost::lexical_cast<float>(result[2]);
            float startY = boost::lexical_cast<float>(result[3]);

			layer->m_actors.push_back(DActorFactory::instance().createEnemy(m_game.lock(), 
				strEnemyType, startX, startY, m_resourceManager));
        }
        else if(boost::istarts_with(strLine, "BACKGROUND"))
        {
            std::vector<std::string> result;
            boost::split(result, strLine, boost::is_any_of(" "));
            std::string backName = "Backgrounds/" + result[1];
            float speedX = boost::lexical_cast<float>(result[2]);
            float speedY = boost::lexical_cast<float>(result[3]);
            boost::shared_ptr<DBackground> back = DActorFactory::instance().createBackground(backName, m_resourceManager);
            back->setScrollingVel(vec2(speedX, speedY));
            layer->setBackground(back);
        }
    }
    return true;
}

void DWorld::addActor(boost::shared_ptr<DIActor> newActor, int nLayer /*= 0*/)
{
    int numLayers = m_layers.size();
    assert(nLayer < numLayers);

    int selectedLayer = numLayers - nLayer - 1;

    boost::shared_ptr<DLayer> layer = m_layers[selectedLayer];
    layer->m_actors.push_back(newActor);
}